﻿using System;
using System.ComponentModel;
using System.Reflection;
using System.ComponentModel.Composition;
using System.Data;
using System.Waf.Applications;
using System.Windows;
using System.Windows.Input;
using TFSBuildMonitor.Applications.Views;
using System.Diagnostics;
using TfsObjects;
using System.IO;
using System.Collections.Generic;

namespace TFSBuildMonitor.Applications.ViewModels
{
    [Export]
    internal class ShellViewModel : ViewModel<IShellView>
    {
        public string Title
        {
            get
            {
                FileVersionInfo info = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
                return string.Format("{0} - {1} (build {2}) [{3}]", info.OriginalFilename, info.ProductVersion.ToString(), info.Comments, ConnectedTo);
            }
        }

        public int TabIndex { get; set; }
        public string DaysFinished
        {
            get { return _daysFinished; }
            set { _daysFinished = value; RaisePropertyChanged("DaysFinished"); }
        }
        private string _daysFinished;

        public string DaysTotals
        {
            get { return _daysTotals; }
            set { _daysTotals = value; RaisePropertyChanged("DaysTotals"); }
        }
        private string _daysTotals;

        public DataView Queue
        {
            get { return _queue; }
            set { _queue = value; RaisePropertyChanged("Queue"); }
        }
        private DataView _queue;

        public DataView Finished
        {
            get { return _finished; }
            set { _finished = value; RaisePropertyChanged("Finished"); }
        }
        private DataView _finished;

        public DataView Totals
        {
            get { return _totals; }
            set { _totals = value; RaisePropertyChanged("Totals"); }
        }
        private DataView _totals;

        public DataView LastCheckIns
        {
            get { return _lastCheckIns; }
            set { _lastCheckIns = value; RaisePropertyChanged("LastCheckIns"); }
        }
        private DataView _lastCheckIns;

        public DataView AllBuilds
        {
            get { return _allBuilds; }
            set { _allBuilds = value; RaisePropertyChanged("AllBuilds"); }
        }
        private DataView _allBuilds;

        public DataView AllProjectAdmins
        {
            get { return _allProjectAdmins; }
            set { _allProjectAdmins = value; RaisePropertyChanged("AllProjectAdmins"); }
        }
        private DataView _allProjectAdmins;

        public string TeamProject
        {
            get { return _teamProject; }
            set { _teamProject = value; RaisePropertyChanged("TeamProject"); }
        }
        private string _teamProject;


        public List<string> Controllers
        {
            get { return _controllers; }
            set { _controllers = value; RaisePropertyChanged("Controllers"); }
        }
        private List<string> _controllers;

        public string SelectedController
        {
            get { return _selectedController; }
            set { _selectedController = value; RaisePropertyChanged("SelectedController"); SetSelectedController(); }
        }
        private string _selectedController;

        public string ConnectedTo
        {
            get { return _connectedTo; }
            set { _connectedTo = value; RaisePropertyChanged("ConnectedTo"); }
        }
        private string _connectedTo;

        public Visibility ProgressVisibility
        {
            get { return _progressVisibility; }
            set { _progressVisibility = value; RaisePropertyChanged("ProgressVisibility"); }
        }
        private Visibility _progressVisibility;

        public bool Connected
        {
            get { return _connected; }
            set
            {
                _connected = value;
                RaisePropertyChanged("Title");
                DisconnectCommand.RaiseCanExecuteChanged();
                QueuedExportCommand.RaiseCanExecuteChanged();
                FinishedExportCommand.RaiseCanExecuteChanged();
                TotalsExportCommand.RaiseCanExecuteChanged();
                GetLastCheckInsCommand.RaiseCanExecuteChanged();
                FinishedRefreshCommand.RaiseCanExecuteChanged();
                TotalsRefreshCommand.RaiseCanExecuteChanged();
                GetAllBuildsCommand.RaiseCanExecuteChanged();
                GetAllProjectAdminsCommand.RaiseCanExecuteChanged();
            }
        }
        private bool _connected;

        public ICommand ConnectCommand { get { return connectCommand; } }
        private readonly DelegateCommand connectCommand;
        public DelegateCommand DisconnectCommand { get { return disconnectCommand; } }
        private readonly DelegateCommand disconnectCommand;
        public DelegateCommand QueuedExportCommand { get { return queuedExportCommand; } }
        private readonly DelegateCommand queuedExportCommand;
        public DelegateCommand FinishedExportCommand { get { return finishedExportCommand; } }
        private readonly DelegateCommand finishedExportCommand;
        public DelegateCommand TotalsExportCommand { get { return totalsExportCommand; } }
        private readonly DelegateCommand totalsExportCommand;
        public DelegateCommand FinishedRefreshCommand { get { return finishedRefreshCommand; } }
        private readonly DelegateCommand finishedRefreshCommand;
        public DelegateCommand TotalsRefreshCommand { get { return totalsRefreshCommand; } }
        private readonly DelegateCommand totalsRefreshCommand;
        public DelegateCommand GetLastCheckInsCommand { get { return getLastCheckInsCommand; } }
        private readonly DelegateCommand getLastCheckInsCommand;
        public DelegateCommand GetAllBuildsCommand { get { return getAllBuildsCommand; } }
        private readonly DelegateCommand getAllBuildsCommand;
        public DelegateCommand GetAllProjectAdminsCommand { get { return getAllProjectAdminsCommand; } }
        private readonly DelegateCommand getAllProjectAdminsCommand;


        public ICommand ExitCommand { get { return exitCommand; } }
        private readonly DelegateCommand exitCommand;

        private int QueueTimer { get { return Properties.Settings.Default.QueueTimer; } }
        System.Windows.Threading.DispatcherTimer timer;

        TfsCollection tfs;

        [ImportingConstructor]
        public ShellViewModel(IShellView view)
            : base(view)
        {
            connectCommand = new DelegateCommand(Connect);
            disconnectCommand = new DelegateCommand(Disconnect, IsConnected);
            queuedExportCommand = new DelegateCommand((o) => RunThread(ExportQueue), o => IsConnected());
            finishedExportCommand = new DelegateCommand((o) => RunThread(ExportFinished), o => IsConnected());
            totalsExportCommand = new DelegateCommand((o) => RunThread(ExportTotals), o => IsConnected());
            finishedRefreshCommand = new DelegateCommand((o) => RunThread(RefreshFinished), o => IsConnected());
            totalsRefreshCommand = new DelegateCommand((o) => RunThread(RefreshTotals), o => IsConnected());
            getLastCheckInsCommand = new DelegateCommand((o) => RunThread(GetLastCheckIns), o => IsConnected());
            getAllBuildsCommand = new DelegateCommand((o) => RunThread(GetAllBuilds), o => IsConnected());
            getAllProjectAdminsCommand = new DelegateCommand((o) => RunThread(GetAllProjectAdmins), o => IsConnected());
            exitCommand = new DelegateCommand(Close);
            ConnectedTo = "Disconnected";
            Connected = false;
            DaysFinished = "-1";
            DaysTotals = "-30";
            SelectedController = "";
            Controllers = new List<string>();
            Queue = new DataView();
            Finished = new DataView();
            Totals = new DataView();
            ProgressVisibility = Visibility.Hidden;
            timer = new System.Windows.Threading.DispatcherTimer();
            timer.Tick += timer_Tick;
            timer.Interval = TimeSpan.FromSeconds(QueueTimer);
            timer.Start();

        }



        public void Show()
        {
            ViewCore.Show();
        }

        private void Close()
        {
            ViewCore.Close();
        }



        private void SetSelectedController()
        {
            RunThread(RefreshQueue);
            RunThread(RefreshFinished);
            RunThread(RefreshTotals);
        }

        public void Save()
        {
        }
        public void SaveAs()
        {
        }

        private static void RunThread(DoWorkEventHandler ev)
        {
            var worker = new BackgroundWorker();
            worker.DoWork += ev;
            worker.RunWorkerAsync();
            worker.Dispose();
        }

        public void Connect()
        {
            tfs = TfsCollection.ConnectTo();
            if (tfs == null)
            {
                ConnectedTo = "Disconnected";
                Controllers = new List<string>();
                Connected = false;
            }
            else
            {
                ConnectedTo = tfs.Collection.Name;
                Controllers = tfs.GetControllers();
                Connected = true;
            }
            SetSelectedController();
        }

        private void Disconnect()
        {
            tfs = null;
            ConnectedTo = "Disconnected";
            Controllers = new List<string>();
            Connected = false;
            SetSelectedController();
        }

        private bool IsConnected()
        {
            return tfs != null;
        }

        private void RefreshQueue(object sender, DoWorkEventArgs e)
        {
            if (tfs == null || string.IsNullOrEmpty(SelectedController))
                Queue = new DataView();
            else
                Queue = tfs.GetQueuedBuilds(SelectedController).Tables["Queue"].DefaultView;
        }

        private void RefreshFinished(object sender, DoWorkEventArgs e)
        {
            ProgressVisibility = Visibility.Visible;

            if (tfs == null || string.IsNullOrEmpty(SelectedController))
                Finished = new DataView();
            else
            {
                if (!DaysFinished.StartsWith("-"))
                    DaysFinished = "-" + DaysFinished;
                int daysFinished = int.Parse(DaysFinished);
                Finished = tfs.GetFinishedBuilds(SelectedController, daysFinished).Tables["Finished"].DefaultView;
            }

            ProgressVisibility = Visibility.Hidden;
        }

        private void RefreshTotals(object sender, DoWorkEventArgs e)
        {
            ProgressVisibility = Visibility.Visible;

            if (tfs == null || string.IsNullOrEmpty(SelectedController))
                Totals = new DataView();
            else
            {
                if (!DaysTotals.StartsWith("-"))
                    DaysTotals = "-" + DaysTotals;
                int daysTotals = int.Parse(DaysTotals);
                Totals = tfs.GetTotalBuilds(SelectedController, daysTotals).Tables["Total"].DefaultView;
            }

            ProgressVisibility = Visibility.Hidden;
        }

        private void GetLastCheckIns(object sender, DoWorkEventArgs e)
        {
            ProgressVisibility = Visibility.Visible;

            if (tfs == null || string.IsNullOrEmpty(SelectedController))
                LastCheckIns = new DataView();
            else
            {
                LastCheckIns = tfs.GetLastCheckIns(SelectedController).Tables["LastCheckIns"].DefaultView;
            }

            ProgressVisibility = Visibility.Hidden;
        }

        private void GetAllBuilds(object sender, DoWorkEventArgs e)
        {
            ProgressVisibility = Visibility.Visible;

            if (tfs == null || string.IsNullOrEmpty(SelectedController))
                AllBuilds = new DataView();
            else
            {
                AllBuilds = tfs.GetAllBuilds(SelectedController).Tables["All"].DefaultView;
            }

            ProgressVisibility = Visibility.Hidden;
        }

        private void GetAllProjectAdmins(object sender, DoWorkEventArgs e)
        {
            ProgressVisibility = Visibility.Visible;

            if (tfs == null || string.IsNullOrEmpty(SelectedController))
                AllProjectAdmins = new DataView();
            else
            {
                AllProjectAdmins = tfs.GetAllProjectAdmins(SelectedController).Tables["All"].DefaultView;
            }

            ProgressVisibility = Visibility.Hidden;
        }


        private void ExportQueue(object sender, DoWorkEventArgs e)
        {
            timer.Stop();
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "queue";
            dlg.DefaultExt = ".xml";
            dlg.Filter = "XML documents (.xml)|*.xml";
            Nullable<bool> result = dlg.ShowDialog();
            if (result == true)
            {
                string filename = dlg.FileName;
                using (TextWriter textWriter = new StreamWriter(filename))
                {
                    Queue.Table.WriteXml(textWriter, XmlWriteMode.IgnoreSchema);
                }
            }
            timer.Start();
        }

        private void ExportFinished(object sender, DoWorkEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "finished"; // Default file name
            dlg.DefaultExt = ".xml"; // Default file extension
            dlg.Filter = "XML documents (.xml)|*.xml"; // Filter files by extension 
            Nullable<bool> result = dlg.ShowDialog();
            if (result == true)
            {
                string filename = dlg.FileName;
                using (TextWriter textWriter = new StreamWriter(filename))
                {
                    Finished.Table.WriteXml(textWriter, XmlWriteMode.IgnoreSchema);
                }
            }
        }

        private void ExportTotals(object sender, DoWorkEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
            dlg.FileName = "totals"; // Default file name
            dlg.DefaultExt = ".xml"; // Default file extension
            dlg.Filter = "XML documents (.xml)|*.xml"; // Filter files by extension 
            Nullable<bool> result = dlg.ShowDialog();
            if (result == true)
            {
                string filename = dlg.FileName;
                using (TextWriter textWriter = new StreamWriter(filename))
                {
                    Totals.Table.WriteXml(textWriter, XmlWriteMode.IgnoreSchema);
                }
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (TabIndex == 0)
                RunThread(RefreshQueue);
        }

    }
}
